using M13.Game.World;
using M13.GameSystem;
using M13.Utility;
using System;
using System.Buffers;
using System.Text;
using M13.DataStructure;
using UnityEngine;

namespace M13.Utility
{
    
    public class RegionDataParser
    {
        static ArrayPool<byte> _arrayPoolOfBoot = ArrayPool<byte>.Create(128, 256);
        public static void RegionCompress(ISaveSystem saveSystem, SaveConfig saveConfig, Vector2Int regionLocalCoord, Region region)
        {
            region.AcquireRegionUnloadTask();
            byte[] regionSingularCompressedData = region.RegionDataArray.DynamicExpansionArray.Array;
            byte[] regionBoot = region.GetRegionBootData();
            byte[] regionData = _arrayPoolOfBoot.Rent(regionSingularCompressedData.Length + regionBoot.Length);
            Buffer.BlockCopy(regionBoot, 0, regionData, 0, regionBoot.Length);
            Buffer.BlockCopy(regionSingularCompressedData, 0, regionData, regionBoot.Length, regionSingularCompressedData.Length);
            saveSystem.CreateRegionFile(saveConfig.name, regionLocalCoord, Clzf2.Compress(regionData));
            _arrayPoolOfBoot.Return(regionData, true);
        }

        public static Region RegionDecompress(ISaveSystem saveSystem, SaveConfig saveConfig, Vector2Int regionLocalCoord)
        {
            byte[] regionData = Clzf2.Decompress(saveSystem.LoadRegionData(saveConfig.name, regionLocalCoord));
            byte[] regionBoot = new byte[6144];
            byte[] regionSingularCompressedData = new byte[regionData.Length - regionBoot.Length];
            Buffer.BlockCopy(regionData, 0, regionBoot, 0, regionBoot.Length);
            Buffer.BlockCopy(regionData, regionBoot.Length, regionSingularCompressedData, 0, regionSingularCompressedData.Length);

            Region region = new Region(regionLocalCoord, regionSingularCompressedData, regionBoot);

            return region;
        }

        public static byte[] Serialize(byte[] compressedCvm, byte[] compressedChm, byte[] compressedCtim)
        {
            byte[] chunkSingularCompressedData = ArrayPool<byte>.Shared.Rent(compressedCvm.Length + compressedChm.Length + compressedCtim.Length);
            Buffer.BlockCopy(compressedCvm, 0, chunkSingularCompressedData, 0, compressedCvm.Length);
            Buffer.BlockCopy(compressedChm, 0, chunkSingularCompressedData, compressedCvm.Length, compressedChm.Length);
            Buffer.BlockCopy(compressedCtim, 0, chunkSingularCompressedData, compressedCvm.Length + compressedChm.Length, compressedCtim.Length);
            return chunkSingularCompressedData;
        }


        public static void Deserialize(Vector2Int chunkLocalCoord, byte[] chunkSingularCompressedData, ChunkDataBoot chunkDataBoot, out byte[] cvm, out byte[] chm, out byte[] ctim)
        {
            //��������������������������ľ��棡����������������������
            byte[] compressedCvm = new byte[chunkDataBoot.cvmDataLength];
            byte[] compressedChm = new byte[chunkDataBoot.chmDataLength];
            byte[] compressedCtim = new byte[chunkDataBoot.ctimDatalength];
            //��������������������������ľ��棡����������������������

            Buffer.BlockCopy(chunkSingularCompressedData, 0, compressedCvm, 0, chunkDataBoot.cvmDataLength);
            Buffer.BlockCopy(chunkSingularCompressedData, chunkDataBoot.cvmDataLength, compressedChm, 0, chunkDataBoot.chmDataLength);
            Buffer.BlockCopy(chunkSingularCompressedData, chunkDataBoot.cvmDataLength + chunkDataBoot.chmDataLength, compressedCtim, 0, chunkDataBoot.ctimDatalength);

            

            try
            {
                cvm = Clzf2.Decompress(compressedCvm);
                chm = Clzf2.Decompress(compressedChm);
                ctim = Clzf2.Decompress(compressedCtim);
            }
            catch
            {
                Debug.LogError($"���飺{chunkLocalCoord},������{chunkDataBoot.dataOffset}, �ܳ��ȣ�{chunkSingularCompressedData.Length}, �����ݣ�{BytesToHexString.ToHexStringStringBuilder(chunkSingularCompressedData)}");
                cvm = null;
                chm = null;
                ctim = null;

            }
            
        }
    }
    public class BytesToHexString
    {
        public static string ToHexStringStringBuilder(byte[] bytes)
        {
            StringBuilder hex = new StringBuilder(bytes.Length * 2);
            foreach (byte b in bytes)
            {
                hex.AppendFormat("{0} ", b);
            }
            return hex.ToString();
        }
    }
}